import React from 'react';
import { Button, Col, Form, Icon, message, Row } from 'antd';
import { TableMethods, TableParam } from '@/common/Hoc/data';
const FormItem = Form.Item;
import utilsStyles from '@/common/styles/utils.less';
import PubSub from 'pubsub-js';

export const SimpleCurd: any = (methods: TableMethods) => (Component: React.ComponentType<any>) => {
  class SimpleCurdClass extends React.Component<any, TableParam> {
    constructor(props: any) {
      super(props);
      this.state = {
        page: 1,
        size: 10,
        pageTotal: 0,
        tableData: [],
        searchParams: {},
        loading: false,
        sortParam: '',
        direction: '',
        filterParams: {},
        expandForm: false,
        initParams: {},
        modalVisible: false,
        currentData: {},
      };
    }

    componentDidMount(): void {
      PubSub.subscribe('refresh', this.refresh);
      this.initData();
    }

    componentWillUnmount(): void {
      PubSub.unsubscribe('refresh');
    }

    /* 初始化列表 */
    initData = () => {
      this.setState(
        {
          page: 1,
          size: 10,
          searchParams: {},
          sortParam: '',
          direction: '',
        },
        () => {
          this.list();
        },
      );
    };

    /* 设置初始化参数 */
    setInitParam = (initParams: any) => {
      this.setState({
        initParams: initParams,
      });
    };

    /*表格变化 分页 排序 筛选*/
    tableChange = (pagination: any, filters: any, sorter: any, extra: any) => {
      let sort = this.generatorSort(sorter);

      this.setState(
        {
          page: pagination.current,
          size: pagination.pageSize,
          filterParams: this.generatorFilters(filters),
          sortParam: sort.sortParam,
          direction: sort.direction,
        },
        () => {
          this.list();
        },
      );
    };

    // 生成filter参数
    generatorFilters = (filters: any) => {
      let param = {};
      if (filters && Object.keys(filters).length > 0) {
        Object.keys(filters).forEach(item => {
          if (filters[item] && filters[item].length > 0) {
            param[item] = filters[item].join('||');
          }
        });
      }
      return param;
    };

    // 生成排序参数
    generatorSort = (sorter: any) => {
      let order = {
        sortParam: '',
        direction: '',
      };
      if (sorter.order) {
        let prop = sorter.columnKey;
        let pre = '';
        if (prop.indexOf('.') > 0) {
          pre = prop.substring(0, prop.indexOf('.'));
          prop = prop.substring(prop.indexOf('.'), prop.length);
        }
        prop = this.objectToTable(prop);
        if (pre) {
          prop = pre + prop;
        }
        order.sortParam = prop;
        order.direction = sorter.order === 'descend' ? '0' : '1';
      }
      return order;
    };

    objectToTable = (data: any) => {
      let reg = new RegExp('[A-Z]', 'g');

      let left = '';
      let right = '';
      let newData = data;
      let offset = 0;
      let res: any[] = [];
      while (res) {
        // @ts-ignore
        res = reg.exec(data);
        if (!res) {
          break;
        }
        let item = res[0];
        // @ts-ignore
        let pos = res.index + offset;
        left = newData.substring(0, pos);
        right = newData.substring(pos + 1, newData.length);
        item = '_' + item.toLocaleLowerCase();
        newData = left + item + right;
      }

      return newData;
    };

    /* 搜索列表 */
    searchData = (form: any, callback: Function, e: React.FormEvent) => {
      e.preventDefault();

      form.validateFields((err: any, fieldsValue: any) => {
        if (err) return;
        let values = {
          ...fieldsValue,
        };
        if (callback) {
          values = callback(values);
        }
        this.setState(
          {
            page: 1,
            searchParams: values,
          },
          () => {
            this.list();
          },
        );
      });
    };

    /*主键删除*/
    handleDelete = (id: any) => {
      if (methods.getDelete) {
        methods.getDelete({ id: id }).then((res: any) => {
          if (res.status === 0) {
            this.refresh();
            message.success('删除成功');
          } else {
            message.error(res.msg);
          }
        });
      }
    };

    /* 重置列表 */
    resetData = (form: any): void => {
      form.resetFields();
      this.setState(
        {
          page: 1,
          searchParams: {},
        },
        () => {
          this.list();
        },
      );
    };

    /* 刷新列表 */
    refresh = () => {
      this.list();
    };

    /*搜索表单展开隐藏切换*/
    toggleForm = () => {
      const { expandForm } = this.state;
      this.setState({
        expandForm: !expandForm,
      });
    };

    /*渲染搜索表单*/
    renderForm = (form: any, searchColumns: any, callback?: Function) => {
      const { expandForm } = this.state;
      return expandForm
        ? this.renderAdvancedForm(form, searchColumns, callback)
        : this.renderSimpleForm(form, searchColumns, callback);
    };

    renderSimpleForm(form: any, searchColumns: any, callback?: Function) {
      const { getFieldDecorator } = form;

      let pick = searchColumns.length > 2;
      if (pick) {
        searchColumns = searchColumns.splice(0, 2);
      }

      return (
        <Form layout="inline" onSubmit={this.searchData.bind(this, form, callback)}>
          <Row type="flex" justify="start" gutter={{ md: 8, lg: 24, xl: 48 }}>
            {searchColumns.map((searchColumn: any, index: number) => {
              return (
                <Col key={index} md={8} sm={24}>
                  {searchColumn.render ? (
                    searchColumn.render(form)
                  ) : (
                    <FormItem label={searchColumn.title}>
                      {getFieldDecorator(searchColumn.name)(searchColumn.content)}
                    </FormItem>
                  )}
                </Col>
              );
            })}
            <Col md={8} sm={24}>
              <span className={utilsStyles.submitButtons}>
                <Button type="primary" htmlType="submit">
                  查询
                </Button>
                <Button style={{ marginLeft: 8 }} onClick={this.resetData.bind(this, form)}>
                  重置
                </Button>
                {pick ? (
                  <a style={{ marginLeft: 8 }} onClick={this.toggleForm}>
                    展开 <Icon type="down" />
                  </a>
                ) : (
                  ''
                )}
              </span>
            </Col>
          </Row>
        </Form>
      );
    }

    renderAdvancedForm(form: any, searchColumns: any, callback?: Function) {
      const { getFieldDecorator } = form;
      return (
        <Form layout="inline" onSubmit={this.searchData.bind(this, form, callback)}>
          <Row type="flex" justify="start" gutter={{ md: 8, lg: 24, xl: 48 }}>
            {searchColumns.map((searchColumn: any, index: number) => {
              return (
                <Col key={index} md={8} sm={24}>
                  {searchColumn.render ? (
                    searchColumn.render(form)
                  ) : (
                    <FormItem label={searchColumn.title}>
                      {getFieldDecorator(searchColumn.name)(searchColumn.content)}
                    </FormItem>
                  )}
                </Col>
              );
            })}
            <Col md={8} sm={24} offset={(searchColumns.length % 3) * 8}>
              <div style={{ overflow: 'hidden' }}>
                <div style={{ float: 'right', marginBottom: 24 }}>
                  <Button type="primary" htmlType="submit">
                    查询
                  </Button>
                  <Button style={{ marginLeft: 8 }} onClick={this.resetData.bind(this, form)}>
                    重置
                  </Button>
                  <a style={{ marginLeft: 8 }} onClick={this.toggleForm}>
                    收起 <Icon type="up" />
                  </a>
                </div>
              </div>
            </Col>
          </Row>
        </Form>
      );
    }

    /*模态框显示隐藏*/
    handleModalVisible = (flag?: boolean, record?: any) => {
      this.setState({
        modalVisible: !!flag,
        currentData: record || {},
      });
    };

    getParams = () => {
      let locationParams = this.props.match && this.props.match.params;
      if (!locationParams) {
        locationParams = {};
      }
      let searchParam = {
        ...this.state.searchParams,
        ...this.state.filterParams,
        ...this.state.initParams,
        ...locationParams,
      };

      return {
        page: this.state.page,
        size: this.state.size,
        sortParam: this.state.sortParam,
        direction: this.state.direction,
        param: JSON.stringify(searchParam),
      };
    };

    list = () => {
      const params = this.getParams();
      this.setState({
        loading: true,
      });

      if (!methods.getList) {
        return;
      }

      methods
        .getList(params)
        .then((res: any) => {
          if (res.status === 0) {
            this.setState({
              tableData: res.data.records,
            });
            if (res.data.total) {
              this.setState({
                pageTotal: res.data.total,
              });
            }
          } else {
            message.error(res.msg);
          }
          this.setState({
            loading: false,
          });
        })
        .catch((res: any) => {
          this.setState({
            loading: false,
          });
        });
    };
    childRef = null;
    render() {
      const { pageTotal, tableData, loading, modalVisible, currentData } = this.state;

      return (
        <Component
          getInstance={(n: any) => {
            this.childRef = n;
          }}
          {...this.props}
          pageTotal={pageTotal}
          tableData={tableData}
          tableLoading={loading}
          modalVisible={modalVisible}
          currentData={currentData}
          setInitParam={this.setInitParam}
          renderForm={this.renderForm}
          searchData={this.searchData}
          resetData={this.resetData}
          tableChange={this.tableChange}
          refresh={this.refresh}
          handleModalVisible={this.handleModalVisible}
          handleDelete={this.handleDelete}
        />
      );
    }
  }
  return SimpleCurdClass;
};
